package com.skd.mall.order.service.impl;

import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.skd.common.constant.OrderConstant;
import com.skd.common.exception.NoStockExecption;
import com.skd.common.utils.R;
import com.skd.common.vo.MemberVO;
import com.skd.mall.order.dao.OrderItemDao;
import com.skd.mall.order.dto.OrderCreatDto;
import com.skd.mall.order.dto.SeckillOrderDto;
import com.skd.mall.order.entity.OrderItemEntity;
import com.skd.mall.order.fegin.CartServiceFegin;
import com.skd.mall.order.fegin.MemberServiceFegin;
import com.skd.mall.order.fegin.ProductService;
import com.skd.mall.order.fegin.WareServiceFrgin;
import com.skd.mall.order.interceptor.AuthInterceptor;
import com.skd.mall.order.service.OrderItemService;
import com.skd.mall.order.utils.OrderMsgProducer;
import com.skd.mall.order.vo.*;

import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.skd.common.utils.PageUtils;
import com.skd.common.utils.Query;

import com.skd.mall.order.dao.OrderDao;
import com.skd.mall.order.entity.OrderEntity;
import com.skd.mall.order.service.OrderService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;


@Service("orderService")
public class OrderServiceImpl extends ServiceImpl<OrderDao, OrderEntity> implements OrderService {

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<OrderEntity> page = this.page(
                new Query<OrderEntity>().getPage(params),
                new QueryWrapper<OrderEntity>()
        );

        return new PageUtils(page);
    }

    @Autowired
    private OrderItemDao orderItemDao;
    @Autowired
    private MemberServiceFegin memberServiceFegin;

    @Autowired
    private CartServiceFegin cartServiceFegin;

    @Autowired
    private ThreadPoolExecutor executor;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private ProductService productService;

    @Autowired
    private OrderService orderService;

    @Autowired
    private OrderItemService orderItemService;

    @Autowired
    private WareServiceFrgin wareServiceFrgin;

    @Autowired
    private OrderMsgProducer orderMsgProducer;

    @Override
    public OrderConfirmVo confirmOrder() {
        // 获取到 RequestContextHolder 的相关信息
        OrderConfirmVo vo = new OrderConfirmVo();
        MemberVO memberVO = (MemberVO)AuthInterceptor.threadLocal.get();
        // 获取到 RequestContextHolder 的相关信息
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> {
            // 同步主线程中的 RequestContextHolder
            RequestContextHolder.setRequestAttributes(requestAttributes);
            // 1.查询当前登录用户对应的会员的地址信息
            List<MemberAddressVo> address = memberServiceFegin.getAddressById(memberVO.getId());
            vo.setAddress(address);
        }, executor);
        CompletableFuture<Void> future2 = CompletableFuture.runAsync(() -> {
            // 同步主线程中的 RequestContextHolder
            RequestContextHolder.setRequestAttributes(requestAttributes);
            // 2.查询购物车中选中的商品信息
            List<OrderItemVo> cartItem = cartServiceFegin.getUserCartItem(memberVO.getId());
            vo.setItems(cartItem);
        }, executor);
        try {
            CompletableFuture.allOf(future1,future2).get();
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 3.计算订单的总金额和需要支付的总金额 VO自动计算
        //4生成放重token
        String token = UUID.randomUUID().toString().replaceAll("-", "");
        //存储在redis中
        redisTemplate.opsForValue().set(OrderConstant.ORDER_TOKEN_PREFIX+":"+memberVO.getId(),token);
        vo.setOrderToken(token);
        return vo;
    }

    @GlobalTransactional
    @Transactional
    @Override
    public OrderResponseVO submitOrder(OrderSubmitVO vo) throws NoStockExecption{
        OrderResponseVO responseVO = new OrderResponseVO();
        // 获取当前登录的用户信息
        MemberVO memberVO = (MemberVO) AuthInterceptor.threadLocal.get();
        // 1.验证是否重复提交  保证Redis中的token 的查询和删除是一个原子性操作
        String key = OrderConstant.ORDER_TOKEN_PREFIX+":"+memberVO.getId();
        String script = "if redis.call('get',KEYS[1])==ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end";
        Long result = redisTemplate.execute(new DefaultRedisScript<Long>(script, Long.class)
                , Arrays.asList(key)
                , vo.getOrderToken());
        if(result == 0){
            // 表示验证失败 说明是重复提交
            responseVO.setCode(1);
            return responseVO;
        }// 2.创建订单和订单项信息
        OrderCreatDto orderCreateTO = createOrder(vo);
        responseVO.setOrderEntity(orderCreateTO.getOrderEntity());
        // 3.保存订单信息
        saveOrder(orderCreateTO);
        // 4.锁定库存信息
        // 订单号  SKU_ID  SKU_NAME 商品数量
        // 封装 WareSkuLockVO 对象
        WareSkuLockVO wareSkuLockVO = new WareSkuLockVO();
        wareSkuLockVO.setOrderSN(orderCreateTO.getOrderEntity().getOrderSn());
        List<OrderItemVo> orderItemVos = orderCreateTO.getOrderItemEntities().stream().map(item -> {
            OrderItemVo itemVo = new OrderItemVo();
            itemVo.setSkuId(item.getSkuId());
            itemVo.setTitle(item.getSkuName());
            itemVo.setCount(item.getSkuQuantity());
            return itemVo;
        }).collect(Collectors.toList());
        wareSkuLockVO.setItems(orderItemVos);
        //远程锁库存
        R r = wareServiceFrgin.orderLockStock(wareSkuLockVO);
        if(r.getCode() == 0){
            //表示锁定成功
            responseVO.setCode(0);//表示创建订单成功
        }else {
            //表示锁定失败
            responseVO.setCode(2);//库存不足
            throw new NoStockExecption(404L);
        }
        // 5.同步更新用户的会员积分
        // int i = 1 / 0;
        // 订单成功后需要给 消息中间件发送延迟30分钟的关单消息
        orderMsgProducer.sendOrderMessage(orderCreateTO.getOrderEntity().getOrderSn());
        return responseVO;
    }

    @Override
    public PayVo getorderPay(String orderSn) {
        PayVo payVo = new PayVo();
        OrderEntity entity = this.baseMapper.selectOne(
                new QueryWrapper<OrderEntity>().eq("order_sn", orderSn));
        payVo.setOut_trader_no(entity.getOrderSn());
        payVo.setTotal_amount(entity.getTotalAmount().setScale(2, RoundingMode.HALF_UP).toString());
        payVo.setBody(entity.getNote());
        payVo.setSubject(orderSn);
        return payVo;
    }

    /**
     * 更新订单状态
     * @param orderSn
     */
    @GlobalTransactional
    @Transactional
    @Override
    public void handleOrderComplete(String orderSn) {
        //1更新订单状态
        baseMapper.updataStatus(orderSn,OrderConstant.OrderStateEnum.TO_SEND_GOODS.getCode());
        //2更新库存
        List<OrderItemEntity> orderItemEntities = orderItemDao.selectList(
                new QueryWrapper<OrderItemEntity>().eq("order_sn", orderSn)
        );
        List<Long> skuIds = new ArrayList<>();
        List<OrderItemVo> collect = orderItemEntities.stream().map(entity -> {
            OrderItemVo orderItemVo = new OrderItemVo();
            orderItemVo.setSkuId(entity.getSkuId());
            skuIds.add(entity.getSkuId());
            orderItemVo.setCount(entity.getSkuQuantity());
            return orderItemVo;
        }).collect(Collectors.toList());
        wareServiceFrgin.updateStock(collect);
        //3删除购物车已支付商品
        cartServiceFegin.updateCartLists(skuIds);
    }

    /**
     * 快速创建秒杀订单
     * @param seckillOrderDto
     */
    @Transactional
    @Override
    public void quickCreateOrder(SeckillOrderDto seckillOrderDto) {
        OrderEntity orderEntity = new OrderEntity();
        orderEntity.setOrderSn(seckillOrderDto.getOrderSN());
        orderEntity.setStatus(OrderConstant.OrderStateEnum.FOR_THE_PAYMENT.getCode());
        orderEntity.setMemberId(seckillOrderDto.getMemberId());
        orderEntity.setTotalAmount(seckillOrderDto.getSeckillPrice().multiply(new BigDecimal(seckillOrderDto.getNum())));
        //储存收货人信息
        MemberAddressVo memberAddressVo = memberServiceFegin.getAddress(seckillOrderDto.getMemberId());
        MemberVO memberVO = (MemberVO) AuthInterceptor.threadLocal.get();
        orderEntity.setMemberUsername(memberVO.getUsername());
        orderEntity.setReceiverName(memberAddressVo.getName());
        orderEntity.setReceiverDetailAddress(memberAddressVo.getDetailAddress());
        this.save(orderEntity);

        OrderItemEntity orderItemEntity = new OrderItemEntity();
        orderItemEntity.setOrderSn(seckillOrderDto.getOrderSN());
        orderItemEntity.setSkuPrice(seckillOrderDto.getSeckillPrice());
        orderItemEntity.setSkuId(seckillOrderDto.getSkuId());
        orderItemEntity.setRealAmount(seckillOrderDto.getSeckillPrice().multiply(new BigDecimal(seckillOrderDto.getNum())));
        orderItemEntity.setSkuQuantity(seckillOrderDto.getNum());
        //商品详细信息
        Long[] spuIds = {seckillOrderDto.getSkuId()};
        List<OrderItemSpuInfoVo> infoSpuId = productService.getOrderItemSpuInfoSpuId(spuIds);
        for (OrderItemSpuInfoVo orderItemSpuInfoVo : infoSpuId) {
         orderItemEntity.setSpuId(orderItemSpuInfoVo.getId());
         orderItemEntity.setSpuName(orderItemSpuInfoVo.getSpuName());
         orderItemEntity.setSpuPic(orderItemSpuInfoVo.getImg());
         orderItemEntity.setSpuBrand(orderItemSpuInfoVo.getBrandName());
         orderItemEntity.setCategoryId(orderItemSpuInfoVo.getCatalogId());
        }
        orderItemService.save(orderItemEntity);
    }

    private void saveOrder(OrderCreatDto orderCreateTO) {
        boolean save = orderService.save(orderCreateTO.getOrderEntity());
        boolean saveBatch = orderItemService.saveBatch(orderCreateTO.getOrderItemEntities());
    }

    private OrderCreatDto createOrder(OrderSubmitVO vo) {
        OrderCreatDto createTO = new OrderCreatDto();
        // 创建订单
        OrderEntity orderEntity = buildOrder(vo);
        createTO.setOrderEntity(orderEntity);
        // 创建OrderItemEntity 订单项
        List<OrderItemEntity> orderItemEntitys = buildOrderItems(orderEntity.getOrderSn());
        // 根据订单项计算出支付总额
        BigDecimal totalAmount = new BigDecimal(0);
        for (OrderItemEntity orderItemEntity : orderItemEntitys) {
            BigDecimal total = orderItemEntity.getSkuPrice().multiply(new BigDecimal(orderItemEntity.getSkuQuantity()));
            totalAmount = totalAmount.add(total);
        }
        orderEntity.setTotalAmount(totalAmount);
        createTO.setOrderItemEntities(orderItemEntitys);
        return createTO;
    }

    private List<OrderItemEntity> buildOrderItems(String orderSn) {
        List<OrderItemEntity> orderItemEntities = new ArrayList<>();
        // 获取购物车中的商品信息 选中的
        List<OrderItemVo> cartItems = cartServiceFegin.getUserCartItem(1L);
        if(cartItems != null && cartItems.size() > 0){
            List<Long> spuIds = new ArrayList<>();
            for (OrderItemVo orderItemVo : cartItems) {
                if(!spuIds.contains(orderItemVo.getSpuId())){
                    spuIds.add(orderItemVo.getSpuId());
                }
            }
            Long[] spuIdsArray = new Long[spuIds.size()];
            spuIdsArray = spuIds.toArray(spuIdsArray);
            // 远程调用商品服务获取到对应的SPU信息
            List<OrderItemSpuInfoVo> spuInfos = productService.getOrderItemSpuInfoSpuId(spuIdsArray);
            Map<Long, OrderItemSpuInfoVo> map = spuInfos.stream().collect(Collectors.toMap(OrderItemSpuInfoVo::getId, item -> item));
            for (OrderItemVo userCartItem : cartItems) {
                // 获取到商品信息对应的 SPU信息
                OrderItemSpuInfoVo spuInfo  = map.get(userCartItem.getSpuId());
                OrderItemEntity orderItemEntity = buildOrderItem(userCartItem,spuInfo);
                // 绑定对应的订单编号
                orderItemEntity.setOrderSn(orderSn);
                orderItemEntities.add(orderItemEntity);
            }
        }
        // 统一根据SKUID查询出对应的SPU的信息
        return orderItemEntities;

    }

    /**
     * 根据一个购物车中的商品创建对应的 订单项
     * @param userCartItem
     * @return
     */
    private OrderItemEntity buildOrderItem(OrderItemVo userCartItem,OrderItemSpuInfoVo spuInfo) {
        OrderItemEntity entity = new OrderItemEntity();
        // SKU信息
        entity.setSkuId(userCartItem.getSkuId());
        entity.setSkuName(userCartItem.getTitle());
        entity.setSkuPic(userCartItem.getImage());
        entity.setSkuQuantity(userCartItem.getCount());
        entity.setSkuPrice(userCartItem.getPrice());
        List<String> skuAttr = userCartItem.getSkuAttr();
        String skuAttrStr = StringUtils.collectionToDelimitedString(skuAttr, ";");
        entity.setSkuAttrsVals(skuAttrStr);
        // SPU信息
        entity.setSpuId(spuInfo.getId());
        entity.setSpuBrand(spuInfo.getBrandName());
        entity.setCategoryId(spuInfo.getCatalogId());
        entity.setSpuPic(spuInfo.getImg());
        // 优惠信息 忽略
        // 积分信息
        entity.setGiftGrowth(userCartItem.getPrice().intValue());
        entity.setGiftIntegration(userCartItem.getPrice().intValue());
        return entity;
    }

    private OrderEntity buildOrder(OrderSubmitVO vo) {
        // 创建OrderEntity
        OrderEntity orderEntity = new OrderEntity();
        // 创建订单编号
        // 创建一个 DateTimeFormatter 对象，定义不使用分隔符的格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
        // 获取当前日期和时间
        LocalDateTime now = LocalDateTime.now();
        // 使用自定义的格式化器格式化日期和时间
        String formattedDateTime = now.format(formatter);
        Random random = new Random();
        // 生成一个四位长度的随机数字，最高位不为0
        int fourDigitNumber = 1000 + random.nextInt(9000);
        if (fourDigitNumber < 1000) {
            fourDigitNumber += 1000;
        }
        String orderSn = fourDigitNumber+formattedDateTime;
        orderEntity.setOrderSn(orderSn);
        //创建时间
        orderEntity.setCreateTime(new Date());
        //获取会员信息
        MemberVO memberVO = (MemberVO) AuthInterceptor.threadLocal.get();
        orderEntity.setMemberId(memberVO.getId());
        orderEntity.setMemberUsername(memberVO.getUsername());
        // 根据收获地址ID获取收获地址的详细信息
        MemberAddressVo address = memberServiceFegin.getAddress(vo.getAddrId());
        orderEntity.setReceiverName(address.getName());
        orderEntity.setReceiverPhone(address.getPhone());
        orderEntity.setReceiverProvince(address.getProvince());
        orderEntity.setReceiverCity(address.getCity());
        orderEntity.setReceiverRegion(address.getRegion());
        orderEntity.setReceiverDetailAddress(address.getDetailAddress());
        // 设置订单的状态
        orderEntity.setStatus(OrderConstant.OrderStateEnum.FOR_THE_PAYMENT.getCode());
        return orderEntity;
    }
}